#include <mythtv/mythcontext.h>

#include "globalsettings.h"
#include "globals.h"
#include "programmedlg.h"
#include "parentalcontrols.h"

#include <map>
#include <vector>

#include <qdir.h>

namespace
{
// General Settings
HostComboBox *ProgrammeDefaultParentalLevel()
{
    HostComboBox *gc = new HostComboBox("iPlayerDefaultParentalLevel");
    gc->setLabel(QObject::tr("Starting Parental Level"));
    gc->addSelection(QObject::tr("4 - Highest"),
                     QString::number(ParentalLevel::plHigh));
    gc->addSelection(QObject::tr("1 - Lowest"),
                     QString::number(ParentalLevel::plLowest));
    gc->addSelection(QString::number(ParentalLevel::plLow));
    gc->addSelection(QString::number(ParentalLevel::plMedium));
    gc->setHelpText(QObject::tr("This is the 'level' that MythiPlayer starts at. "
                    "Any programmes with a level at or below this will be shown in "
                    "the list or while browsing by default. The Parental PIN "
                    "should be set to limit changing of the default level."));
    return gc;
}

HostComboBox *ProgrammeDefaultView()
{
    HostComboBox *gc = new HostComboBox("Default MythiPlayer View");
    gc->setLabel(QObject::tr("Default View"));
    gc->addSelection(QObject::tr("Gallery"),
                     QString::number(ProgrammeDialog::DLG_GALLERY));
    gc->addSelection(QObject::tr("Listings"),
                     QString::number(ProgrammeDialog::DLG_TREE));
    gc->setHelpText(QObject::tr("The default view for MythiPlayer. "
                    "Other views can be reached via the popup menu available "
                    "via the MENU key."));
    return gc;
}

const QString password_clue =
    QObject::tr("Setting this value to all numbers will make your life "
                "much easier.");

HostLineEdit *ProgrammeAdminPassword()
{
    HostLineEdit *gc = new HostLineEdit("ProgrammeAdminPassword");
    gc->setLabel(QObject::tr("Parental Level 4 PIN"));
    gc->setHelpText(QString("%1 %2")
        .arg(QObject::tr("This PIN is used to enter Parental Control "
                         "Level 4 as well as the Programme Manager."))
        .arg(password_clue));
    return gc;
}

HostLineEdit *ProgrammeAdminPasswordThree()
{
    HostLineEdit *gc = new HostLineEdit("ProgrammeAdminPasswordThree");
    gc->setLabel(QObject::tr("Parental Level 3 PIN"));
    gc->setHelpText(QString("%1 %2")
        .arg(QObject::tr("This PIN is used to enter Parental Control Level 3."))
        .arg(password_clue));
    return gc;
}

HostLineEdit *ProgrammeAdminPasswordTwo()
{
    HostLineEdit *gc = new HostLineEdit("ProgrammeAdminPasswordTwo");
    gc->setLabel(QObject::tr("Parental Level 2 PIN"));
    gc->setHelpText(QString("%1 %2")
        .arg(QObject::tr("This PIN is used to enter Parental Control Level 2."))
        .arg(password_clue));
    return gc;
}

HostCheckBox *ProgrammeAggressivePC()
{
    HostCheckBox *gc = new HostCheckBox("ProgrammeAggressivePC");
    gc->setLabel(QObject::tr("Aggressive Parental Control"));
    gc->setValue(false);
    gc->setHelpText(QObject::tr("If set, you will not be able to return "
                    "to this screen and reset the Parental "
                    "PIN without first entering the current PIN. You have "
                    "been warned."));
    return gc;
}

HostCheckBox *ProgrammeSortIgnoresCase()
{
    HostCheckBox *hcb = new HostCheckBox("mythiplayer.sort_ignores_case");
    hcb->setLabel(QObject::tr("Sorting ignores case"));
    hcb->setValue(true);
    hcb->setHelpText(QObject::tr("If set, case is ignored when sorting "
                                 "entries in a view."));
    return hcb;
}

HostCheckBox *ProgrammeDBFolderView()
{
    HostCheckBox *hcb = new HostCheckBox("mythiplayer.db_folder_view");
    hcb->setLabel(QObject::tr("Show folders for database views"));
    hcb->setValue(true);
    hcb->setHelpText(QObject::tr("If set, sub folders of your programme "
                                 "directory will be shown in supported "
                                 "views."));
    return hcb;
}

HostSpinBox *ProgrammeImageCacheSize()
{
    HostSpinBox *hsb = new HostSpinBox("mythiplayer.ImageCacheSize", 10,
                                       1000, 10);
    hsb->setValue(50);
    hsb->setLabel(QObject::tr("Image cache size"));
    hsb->setHelpText(QObject::tr("This setting determines the number "
                                 "of images MythiPlayer will cache for "
                                 "views."));
    return hsb;
}

HostCheckBox *ProgrammeTreeRemeber()
{
    HostCheckBox *gc = new HostCheckBox("mythiplayer.ProgrammeTreeRemember");
    gc->setLabel(QObject::tr("Programme Tree remembers last selected position"));
    gc->setValue(false);
    gc->setHelpText(QObject::tr("If set, the current position in the Programme "
                                "Tree is persistent."));
    return gc;
}

HostLineEdit *ProgrammeArtworkDirectory()
{
    HostLineEdit *gc = new HostLineEdit("mythiplayer.ArtworkDir");
    gc->setLabel(QObject::tr("Directory that holds movie posters"));
    gc->setValue(MythContext::GetConfDir() + "/MythiPlayer");
    gc->setHelpText(QObject::tr("This directory must exist, and the user "
                    "running MythiPlayer needs to have read/write permission "
                    "to the directory."));
    return gc;
}

HostSpinBox *ProgrammeGalleryRows()
{
    HostSpinBox *gc = new HostSpinBox("ProgrammeGalleryRowsPerPage", 2, 5, 1);
    gc->setLabel(QObject::tr("Rows to display"));
    gc->setValue(3);
    return gc;
}

HostSpinBox *ProgrammeGalleryColumns()
{
    HostSpinBox *gc = new HostSpinBox("ProgrammeGalleryColsPerPage", 2, 6, 1);
    gc->setLabel(QObject::tr("Columns to display"));
    gc->setValue(4);
    return gc;
}

HostCheckBox *ProgrammeGallerySubtitle()
{
    HostCheckBox *gc = new HostCheckBox("ProgrammeGallerySubtitle");
    gc->setLabel(QObject::tr("Show title below thumbnails"));
    gc->setValue(true);
    gc->setHelpText(QObject::tr("If set, the additional text will make the "
                    "thumbnails smaller."));
    return gc;
}

// Player Settings
HostLineEdit *PlayerCommand()
{
    HostLineEdit *gc = new HostLineEdit("mythiplayer.iPlayerCommand");
    gc->setLabel(QObject::tr("Flash iPlayer Command"));
//    gc->setValue("mplayer dvd:// -dvd-device %d -fs -zoom -vo xv");
    gc->setValue("/home/storm/Desktop/flash_player_10_linux_dev/flash_player_10_linux_dev/standalone/release/flashplayer %d");
    gc->setHelpText(QObject::tr("This can be any command to launch an iPlayer stream "
                    "If present, %d will be substituted for the stream url. "));
    return gc;
}


struct ConfigPage
{
    typedef std::vector<ConfigurationGroup *> PageList;

  protected:
    ConfigPage(PageList &pl) : m_pl(pl)
    {
    }

    void Add(ConfigurationGroup *page)
    {
        m_pl.push_back(page);
    }

  private:
    ConfigPage(const ConfigPage &);
    ConfigPage &operator=(const ConfigPage &);

  private:
    PageList &m_pl;
};

struct VConfigPage : public ConfigPage
{
    VConfigPage(PageList &pl, bool luselabel = true, bool luseframe  = true,
                bool lzeroMargin = false, bool lzeroSpace = false) :
        ConfigPage(pl)
    {
        m_vc_page = new VerticalConfigurationGroup(luselabel, luseframe,
                                                   lzeroMargin, lzeroSpace);
        Add(m_vc_page);
    }

    VerticalConfigurationGroup *operator->()
    {
        return m_vc_page;
    }

  private:
    VerticalConfigurationGroup *m_vc_page;
};

class RatingsToPL : public TriggeredConfigurationGroup
{
  public:
    RatingsToPL() : TriggeredConfigurationGroup(false)
    {
        HostCheckBox *r2pl =
                new HostCheckBox("mythiplayer.ParentalLevelFromRating");
        r2pl->setLabel(QObject::tr("Enable automatic Parental Level from "
                                   "rating"));
        r2pl->setValue(false);
        r2pl->setHelpText(QObject::tr("If enabled, searches will automatically "
                                      "set the Parental Level to the one "
                                      "matching the rating below."));
        addChild(r2pl);
        setTrigger(r2pl);

        typedef std::map<ParentalLevel::Level, QString> r2pl_map;
        r2pl_map r2pl_defaults;
        r2pl_defaults.insert(r2pl_map::value_type(ParentalLevel::plLowest,
                tr("G", "PL 1 default search string.")));
        r2pl_defaults.insert(r2pl_map::value_type(ParentalLevel::plLow,
                tr("PG", "PL 2 default search string.")));
        r2pl_defaults.insert(r2pl_map::value_type(ParentalLevel::plMedium,
                tr("PG-13", "PL3 default search string.")));
        r2pl_defaults.insert(r2pl_map::value_type(ParentalLevel::plHigh,
                tr("R:NC-17", "PL4 default search string.")));

        VerticalConfigurationGroup *vcg = new VerticalConfigurationGroup(true);

        for (ParentalLevel pl(ParentalLevel::plLowest);
             pl.GetLevel() <= ParentalLevel::plHigh && pl.good(); ++pl)
        {
            HostLineEdit *hle = new HostLineEdit(QString("mythiplayer.AutoR2PL%1")
                                                 .arg(pl.GetLevel()));
            hle->setLabel(QObject::tr("Level %1").arg(pl.GetLevel()));
            hle->setHelpText(QObject::tr("Ratings containing these strings "
                                         "(separated by :) will be assigned "
                                         "to Parental Level %1.")
                             .arg(pl.GetLevel()));

            r2pl_map::const_iterator def_setting =
                    r2pl_defaults.find(pl.GetLevel());
            if (def_setting != r2pl_defaults.end())
            {
                hle->setValue(def_setting->second);
            }

            vcg->addChild(hle);
        }

        addTarget("0", new VerticalConfigurationGroup(true));
        addTarget("1", vcg);

    }
};


} // namespace

ProgrammeGeneralSettings::ProgrammeGeneralSettings()
{
    ConfigPage::PageList pages;

    VConfigPage page1(pages, false);
    page1->addChild(ProgrammeArtworkDirectory());
    page1->addChild(ProgrammeDefaultView());
    page1->addChild(ProgrammeImageCacheSize());


    // page 2
    VerticalConfigurationGroup *vgal =
            new VerticalConfigurationGroup(true, false);
    vgal->setLabel(QObject::tr("Programme Gallery"));
    vgal->addChild(ProgrammeGalleryColumns());
    vgal->addChild(ProgrammeGalleryRows());
    vgal->addChild(ProgrammeGallerySubtitle());
    VConfigPage page2(pages, false);
    page2->addChild(vgal);

    // page 3
    VerticalConfigurationGroup *pctrl =
            new VerticalConfigurationGroup(true, false);
    pctrl->addChild(ProgrammeDefaultParentalLevel());
    pctrl->addChild(ProgrammeAdminPassword());
    pctrl->addChild(ProgrammeAdminPasswordThree());
    pctrl->addChild(ProgrammeAdminPasswordTwo());
    pctrl->addChild(ProgrammeAggressivePC());
    VConfigPage page3(pages, false);
    page3->addChild(pctrl);

    VConfigPage page4(pages, false);
    page4->addChild(new RatingsToPL());

    int page_num = 1;
    for (ConfigPage::PageList::const_iterator p = pages.begin();
         p != pages.end(); ++p, ++page_num)
    {
        (*p)->setLabel(QObject::tr("General Settings (%1/%2)").arg(page_num)
                       .arg(pages.size()));
        addChild(*p);
    }
}

ProgrammePlayerSettings::ProgrammePlayerSettings()
{
    VerticalConfigurationGroup *programmeplayersettings =
            new VerticalConfigurationGroup(false);
    programmeplayersettings->setLabel(QObject::tr("Player Settings"));
    programmeplayersettings->addChild(PlayerCommand());
    addChild(programmeplayersettings);
}

